package com.qf.base.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

/**
 * projectName: automation
 *
 * @author dongshihao
 * Date:2021/9/26   14:50
 * description:解决实体类对象数据拷贝
 */
public class PropertiesUtil {

    public static void copy(Object source, Object target) {
        //来源
        Class<?> sourceClass = source.getClass();
        //目标
        Class<?> targetClass = target.getClass();
        //获取源的所有的成员
        Field[] declaredFields = sourceClass.getDeclaredFields();
        //遍历成员
        for (int i = 0; i < declaredFields.length; i++) {

            //获取第i个成员
            Field field = declaredFields[i];
            //设置可见性
            field.setAccessible(true);
            //拿到成员名
            String name = field.getName();
            //拿到source同名的target的成员
            Field targetFiled = null;

            try {
                targetFiled = targetClass.getDeclaredField(name);
            } catch (Exception e) {
                continue;
            }
            //数据拷贝
            targetFiled.setAccessible(true);
            try {
                //设置target的targetField成员
                //职位source 的filed成员的值
                targetFiled.set(target, field.get(source));

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 自定义注解
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PropertyName {
        String value() default "";
    }

    /**
     * target 成员上有 properrtyName 注解的情况下，就去 source 上找到对应的值
     * 无 PropertyName 注解的情况下，找到名字相同的成员，赋值值
     *
     * @param source
     * @param target
     */
    public static void copyWithAnnotation(Object source, Object target) {
        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        //获取所有的成员
        Field[] targetFields = targetClass.getDeclaredFields();
        for (int i = 0; i < targetFields.length; i++) {
            targetFields[i].setAccessible(true);
            PropertyName    annotation = targetFields[i].getAnnotation(PropertyName.class);
            String fileName= null;
            if (annotation!=null){
                fileName = annotation.value();
            }else {
                fileName =targetFields[i].getName();
            }

            try {
                Field sourceFiled = sourceClass.getDeclaredField(fileName);
                sourceFiled.setAccessible(true);
                targetFields[i].set(target,sourceFiled.get(source));
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
                continue;
            }

        }
    }

}
